package cn.yunbamboos.db.core;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.yunbamboos.db.ReadInitDataSQL;
import cn.yunbamboos.db.metadata.TableMetadata;
import com.zaxxer.hikari.HikariDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.List;

public class MySQLDB extends BaseDB {

    private static final Logger logger = LoggerFactory.getLogger(MySQLDB.class);

    private static final String DB_DIR = "/home/app/db/mysql/data";

    private boolean init = false;

    @Override
    public void checkDBDir() {
        logger.info("mysql data dir {}", DB_DIR);
        // 目录不存在创建目录
        FileUtil.mkdir(DB_DIR);
        // 判断数据库目录是否为空
        if (FileUtil.isDirEmpty(new File(DB_DIR))) {
            // 解压 data.tar 到数据库目录
            unTar(new File("/home/app/db/mysql/"));
        }
    }

    @Override
    public void checkPid() {
        int num = 0;
        while (true) {
            boolean b = checkProcess("mysqld_safe");
            logger.info("check mysqld_safe running {}", b);
            if (b) {
                break;
            }
            // 拉起MySQL服务
            startProcess(new String[]{"sh", "/home/app/start_mysql.sh"});
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                logger.error(e.getMessage(), e);
            }
            num++;
            if (num > 100) {
                break;
            }
        }
    }

    @Override
    public void connect() {
        String DB_DRIVER = System.getProperty("DB_DRIVER", "com.mysql.cj.jdbc.Driver");
        String DB_IP = System.getProperty("DB_IP", "127.0.0.1");
        String DB_PORT = System.getProperty("DB_PORT", "3306");
        String DB_NAME = System.getProperty("DB_NAME");
        String DB_USER = System.getProperty("DB_USER", "root");
        String DB_PASSWORD = System.getProperty("DB_PASSWORD", "root");
        dataSource = new HikariDataSource();
        dataSource.setDriverClassName(DB_DRIVER);
        dataSource.setJdbcUrl(StrUtil.format("jdbc:mysql://{}:{}/mysql?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true", DB_IP, DB_PORT, DB_NAME));
        dataSource.setUsername(DB_USER);
        dataSource.setPassword(DB_PASSWORD);
        dataSource.setAutoCommit(false);
        dataSource.setMaximumPoolSize(10);
        dataSource.setMinimumIdle(1);
    }

    @Override
    public boolean existDB() {
        String DB_NAME = System.getProperty("DB_NAME");
        String sql = StrUtil.format("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '{}'", DB_NAME);
        boolean b = executeExistTableSql(sql);
        logger.info("{} {}", sql, b);
        return b;
    }

    @Override
    public void createDB() {
        String DB_NAME = System.getProperty("DB_NAME");
        logger.info("创建库 {}", DB_NAME);

        String sql = StrUtil.format("CREATE DATABASE `{}`", DB_NAME);

        executeCreateTableSql(sql);

        this.init = true;
    }

    @Override
    public boolean existTable(TableMetadata tableMetadata) {
        String DB_NAME = System.getProperty("DB_NAME");
        String sql = StrUtil.format("SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{}' AND TABLE_NAME = '{}'", DB_NAME, tableMetadata.getName());
        logger.info("execute exist table sql {}", sql);
        return executeExistTableSql(sql);
    }

    @Override
    public void createTable(TableMetadata tableMetadata) {
        String sql = tableMetadata.toCreateTableSql();
        logger.info("execute create table sql \n{}", sql);
        executeCreateTableSql(sql);
    }

    public void initDataSQL(ReadInitDataSQL read){
        if(this.init){
            String DB_NAME = System.getProperty("DB_NAME");
            List<String> sqlList = read.read();
            for (String sql : sqlList) {
                if(StrUtil.isBlank(sql) || sql.startsWith("#")){
                    continue;
                }
                String s = StrUtil.format(sql, DB_NAME);
                logger.info("execute init sql {}", s);
                executeUpdate(s);
            }
        }
    }

}
